package com.me.myFramework.aop22.aop112;

import com.me.myFramework.aop22.aop112.intercept.method.AfterReturningAdviceInterceptor112;
import com.me.myFramework.aop22.aop112.intercept.method.MethodBeforeAdviceInterceptor112;
import com.me.myFramework.aop22.aop112.intercept.method.MethodInterceptor112;
import org.aopalliance.aop.Advice;
import org.springframework.aop.Advisor;
import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.aop.framework.adapter.DefaultAdvisorAdapterRegistry;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * 《AOP-112》：  <br><br>
 * 
 * TODO 提取 getProxy方法，专门负责创建代理类。<br><br>
 *  提取 getInterceptor方法，根据 Advice 创建 MethodInterceptor
 */
public class ProxyFactory112 {

    private Object target;
    private Advice advice;

    public ProxyFactory112(Object target, Advice advice) {
        this.target = target;
        this.advice = advice;
    }

    public Object getProxy() {
        return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                if (isCustomMethod(method.getName())) {
                    MethodInterceptor112 interceptor = getInterceptor();
                    if (interceptor != null) {
                        return interceptor.invoke(method, args, target);
                    }
                }

                return method.invoke(target, args);
            }
        });
    }

    /**
     * 筛选出当前正在执行的方法适用的 advice（增强），并转换成 拦截器（执行增强逻辑的执行器）。
     * 逻辑类似 {@link DefaultAdvisorAdapterRegistry#getInterceptors(Advisor) AdvisedSupport#getInterceptorsAndDynamicInterceptionAdvice}
     *
     * @return  匹配当前方法的拦截器
     */
    private MethodInterceptor112 getInterceptor() {
        if (this.advice == null) {
            return null;
        }

        /**
         * 类似 {@link org.springframework.aop.framework.adapter.MethodBeforeAdviceAdapter#supportsAdvice(Advice)}
         */
        if (advice instanceof MethodBeforeAdvice) {
            return new MethodBeforeAdviceInterceptor112((MethodBeforeAdvice) advice);
        } else if (advice instanceof AfterReturningAdvice) {
            return new AfterReturningAdviceInterceptor112((AfterReturningAdvice) advice);
        } else {
            throw new RuntimeException("GG, 未知的 Advice");
        }
    }

    private boolean isCustomMethod(String methodName) {
        return !("toString".equals(methodName) || "hashCode".equals(methodName) || "equals".equals(methodName)
                || "clone".equals(methodName));
    }

}
